package com.example.csmall.product.service.impl;

import com.example.csmall.product.ex.ServiceException;
import com.example.csmall.product.mapper.CategoryMapper;
import com.example.csmall.product.pojo.dto.CategoryAddNewDTO;
import com.example.csmall.product.pojo.entity.Category;
import com.example.csmall.product.pojo.vo.CategoryListByParentIdVO;
import com.example.csmall.product.pojo.vo.CategoryListItemVO;
import com.example.csmall.product.pojo.vo.CategoryStandardVO;
import com.example.csmall.product.repository.CategoryCacheRepository;
import com.example.csmall.product.service.CategoryService;
import com.example.csmall.product.web.ServiceCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    CategoryMapper categoryMapper;

    @Autowired
    CategoryCacheRepository categoryCacheRepository;

    @Override
    public void addNew(CategoryAddNewDTO categoryAddNewDTO) {
        //名字不允许重复
        String name = categoryAddNewDTO.getName();
        int countByName = categoryMapper.countByName(name);
        if (countByName > 0) {
            String message = "分类添加失败，分类名称已存在！";
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        //补充depth属性
        //如果，DTO中的parent_id为0
        Long parentId = categoryAddNewDTO.getParentId();
        //深度为 0+1
        Integer depth;
        CategoryStandardVO standardById = null;
        if (parentId == 0) {
            depth = 1;
        } else {
            //当设置了父类id，将parent_id属性作为查询参数查询对应的表记录
            standardById = categoryMapper.getStandardById(parentId);
            //判断记录是否存在
            if (standardById == null) {
                //没查到抛出异常
                String message = "分类添加失败，您输入的父类ID不存在！";
                throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
            } else {
                //根据父分类的depth+1
                depth = standardById.getDepth() + 1;
            }
        }

        //创建Category对象
        Category category = new Category();
        BeanUtils.copyProperties(categoryAddNewDTO, category);
        //根据处理好的数据补充对象属性
        category.setDepth(depth);
        //IsParent默认添加为0，后续在根据添加在进行补充
        category.setIsParent(0);
        //执行数据添加方法
        int rows = categoryMapper.insert(category);
        if (rows != 1) {
            String message = "添加类别失败，服务器正忙，请稍后重试!";
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }

        //如果此分类的父类id不为0 并且 此分类是否为父级的标注为0的情况下
        if (parentId != 0 && standardById.getIsParent() == 0) {
            Category updateParentCategory = new Category();
            updateParentCategory.setId(parentId);
            updateParentCategory.setIsParent(1);
            rows = categoryMapper.updateById(updateParentCategory);
            if (rows != 1) {
                String message = "添加类别失败，服务器正忙，请稍后重试!";
                throw new ServiceException(ServiceCode.ERR_UPDATE, message);
            }
        }

    }

    @Override
    public void deleteById(Long id) {
        //调用mapper的方法查询数据详情
        CategoryStandardVO standardById = categoryMapper.getStandardById(id);
        //判断查询的结果是否为null，如果时，抛出异常.
        if (standardById == null) {
            String message = "删除数据失败，数据不存在";
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        //判断查询的结果的isParent是否为1，为1代表此分类是一个父类 存在子类
        if (standardById.getIsParent() == 1) {
            String message = "删除数据失败，此分类下存在子级分类!";
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }
        //调用mapper对象的方法执行删除方法
        int rows = categoryMapper.deleteById(id);
        //判断删除的结果是否符合预期
        if (rows != 1) {
            String message = "删除分类失败，服务器正忙，请稍后重试!";
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        }
        //如果当前分类的父类ID已经是0的这种小概率bug事件，那么此处就不会更改此分类的父类id的isParent(是否为父类)的属性
        if (standardById.getParentId() != 0) {
            //当删除成功时我们应该判断当前分类的父类是否还存在子类
            int countByParentId = categoryMapper.countByParentId((long) standardById.getParentId());
            //当数据统计数量为0时执行修改类中方法
            if (countByParentId == 0) {
                Category category = new Category();
                category.setId((long) standardById.getParentId());
                category.setIsParent(0);
                rows = categoryMapper.updateById(category);
                if (rows != 1) {
                    String message = "删除分类失败，服务器正忙，请稍后重试!";
                    throw new ServiceException(ServiceCode.ERR_UPDATE, message);
                }
            }
        }
    }

    @Override
    public void setEnable(Long id) {
        //1表示打开启用
        this.updateEnableById(id, 1);
    }

    @Override
    public void setDisable(Long id) {
        //0表示关闭启用
        this.updateEnableById(id, 0);
    }

    /**
     * 此方法实现分类的启用和禁用状态
     *
     * @param id
     * @param enable
     */
    private void updateEnableById(Long id, Integer enable) {
        //判断当前id的数据是否存在
        CategoryStandardVO standardById = categoryMapper.getStandardById(id);
        if (standardById == null) {
            String message = ENABLE_TEXT[enable] + "类别失败，所访问的类别不存在!";
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        //判断当前id对应的数据的启用状态，如果当前记录的启用状态和enable一样抛出异常
        if (enable.equals(standardById.getEnable())) {
            String message = ENABLE_TEXT[enable] + "类别状态失败，目前该类别已经是[" + ENABLE_TEXT[enable] + "]状态";
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }

        //创建直接对应数据库的对象，用来执行mapper中的修改方法
        Category category = new Category();
        category.setId(id);
        category.setEnable(enable);
        //执行修改
        int rows = categoryMapper.updateById(category);
        if (rows != 1) {
            String message = ENABLE_TEXT[enable] + "类别失败,服务器正忙，请稍后尝试";
            throw new ServiceException(ServiceCode.ERR_UNKNOWN, message);
        }
    }

    @Override
    public void startDisplay(Long id) {
        updateDisplayById(id,1);
    }

    @Override
    public void forbiddenDisplay(Long id) {
        updateDisplayById(id,0);
    }

    /**
     * 此方法实现导航的启用和禁用状态
     *
     * @param id
     * @param display
     */
    private void updateDisplayById(Long id, Integer display) {
        //判断当前id的数据是否存在
        CategoryStandardVO standardById = categoryMapper.getStandardById(id);
        if (standardById == null) {
            String message = ENABLE_TEXT[display] + "类别导航状态失败，所访问的类别不存在!";
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        //判断当前id对应的数据的导航启用状态，如果当前记录的启用状态和display一样抛出异常
        if (display.equals(standardById.getIsDisplay())) {
            String message = ENABLE_TEXT[display] + "类别导航状态失败，目前该类别已经是[" + ENABLE_TEXT[display] + "]状态";
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }

        //创建直接对应数据库的对象，用来执行mapper中的修改方法
        Category category = new Category();
        category.setId(id);
        category.setIsDisplay(display);
        //执行修改
        int rows = categoryMapper.updateById(category);
        if (rows != 1) {
            String message = ENABLE_TEXT[display] + "类别导航状态失败,服务器正忙，请稍后尝试";
            throw new ServiceException(ServiceCode.ERR_UNKNOWN, message);
        }
    }

    @Override
    public List<CategoryListByParentIdVO> listByParentId(Long parentId) {
        //根据父类id查询数据
        List<CategoryListByParentIdVO> categoryListByParentIdVOS = categoryMapper.listByParentId(parentId);
        return categoryListByParentIdVOS;
    }

    @Override
    public List<CategoryListItemVO> list() {
        List<CategoryListItemVO> list = categoryCacheRepository.list();
        return list;
    }

    /**
     * 重建缓存
     */
    @Override
    public void rebuildCache() {
        boolean delete = categoryCacheRepository.delete();
        categoryCacheRepository.save(categoryMapper.list());
        log.debug("已经重建categoryCache缓存信息:");
    }


}
